<template>
  <div class="chat-content-wrapper f-g f-c a-c">
    <div class="content-box f-g f-c a-c" id="contentBox">
      <div class="chat-header-logo" style="margin-top: -20px;margin-bottom: 20px">
        <img style="width: 480px" src="@/assets/images/layout-bg.png" alt="">
        <div style="margin-top: -20px">
          <h1>灵溪</h1>
          <p class="subtitle">让人工智能融入您的工作流程</p>
        </div>
      </div>
      <div class="content" ref="messageContainer" @scroll="handleScroll">
        <div v-if="isLoadingMore" class="loading-more">
          <i class="el-icon-loading"></i>
          <span>加载更多消息...</span>
        </div>
        <div class="message-item" v-if="!messageList.length && !isLoadingMore">
          <div class="friend friend-avatar-box">
            <div class="avatar">
              <img src="@/assets/images/msg_logo.png" alt="">
            </div>
            <div class="name">
              灵溪AI
            </div>
          </div>
          <div class="friend">
            <div class="message friend-message">
              😉Hi，I'm 灵溪AI～  请问我可以帮您什么？
            </div>
          </div>
        </div>
        <div class="message-item" v-for="item in messageListShow" :key="item.id">
          <template v-if="item.mode === 'chat'">
            <div class="my" v-if="item.role === 'user'">
              <div class="message member-message">
                <span>{{ item.content }}</span>
              </div>
            </div>
            <div class="friend friend-avatar-box" v-if="item.role === 'assistant'">
              <div class="avatar">
                <img src="@/assets/images/msg_logo.png" alt="">
              </div>
              <div class="name">灵溪AI</div>
            </div>
            <div class="friend" v-if="item.role === 'assistant'">
              <div class="message friend-message">
                <img style="width: 77px;height: 40px;position:absolute;left: 50%;top: 50%;transform: translate(-50%,-50%)" src="@/assets/chat_loading.gif" v-if="!item.answer && !item.id" alt="">
                <!-- 思考过程展示 -->
                <div v-if="item.reasoning" class="reasoning-box">
                  <div class="reasoning-header" @click="toggleReasoning(item)">
                    <i class="el-icon-info"></i>
                    思考过程
                    <i :class="['el-icon-arrow-right', item.showReasoning ? 'expanded' : '']"></i>
                  </div>
                  <div v-show="item.showReasoning" class="reasoning-content">
                    <MarkdownRenderer
                      :content="item.reasoning"
                      ref="reasoningRenderer"
                    ></MarkdownRenderer>
                  </div>
                </div>
                <!-- 回答内容 -->
                <MarkdownRenderer
                    class="markdown-body"
                    :content="item.answer"
                    ref="markdownRenderer"
                ></MarkdownRenderer>
              </div>
            </div>
          </template>
          <template v-if="item.mode === 'line'">
            <div class="question-title message-line" style="margin-top: 8px">
              <div class="question-line question-line-start"></div>
              <div class="question">{{ item.message }}</div>
              <div class="question-line question-line-end"></div>
            </div>
          </template>
        </div>
      </div>
    </div>
    <div class="footer f-s">
      <div :class="['input-box', isFocus ? 'focus' : '']">
        <el-input
            style="height: 80px"
            v-model="message"
            type="textarea"
            :autosize="{ minRows: 1, maxRows: 5 }"
            :placeholder="`使用 ${currentModel} 开始对话...`"
            @keydown.native.enter="handleEnterKey"
            @focus="handleFocus"
            @blur="handleBlur"
            clearable
        />
        <div :class="['right-box', message ? '' : 'empty-message']">
          <div class="static">{{ message.length }}</div>
          <img class="clear-icon" v-if="message" src="@/assets/clear.png" alt="" @click="message = ''">
          <div class="d-line"></div>
          <div :class="['send-icon']" @click="sendMessage">
            <img v-if="message && !isGenerating" src="@/assets/发送.png" alt="">
            <img v-else src="@/assets/待发送.png" alt="">
          </div>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
import dayjs from 'dayjs'
import MarkdownRenderer from "@/components/MarkdownRenderer.vue";
import {http} from "@/api";
export default {
  name: "index",
  components: {
    MarkdownRenderer
  },
  data() {
    return {
      messageList: [],
      isFocus: false,
      message: '',
      currentModel: '',
      conversationId: '',
      isLoading: false,
      page: 0,
      pageSize: 10,
      total: 0,
      isLoadingMore: false,
      noMore: false,
      // 正在回答中
      isGenerating: false
    }
  },
  async created() {
    this.conversationId = this.$route.query.conversationId || ''
    // 从路由参数获取模型
    this.currentModel = this.$route.query.model || ''
    if (this.conversationId) {
      await this.loadMessages()
      this.setScroll()
    }
  },
  mounted() {
  },
  beforeDestroy() {
  },
  computed: {
    messageListShow() {
      // 整个消息列表需要进行时间计算分组，与当前时间对比超过24点，显示日期时间，所有消息之间的间隔超过10分钟，需要显示时间
      let list = []
      let lastTime = 0
      // 数据是倒叙的
      let newList = this.messageList
      newList.forEach((item,index) => {
        let create_time = item.create_time * 1000 || new Date().getTime()
        let message = ''

        if (index === 0 || create_time - lastTime >= 60 * 1000 * 10) {
          // 今年之前显示年月日时分，今年显示月日时分，今天显示时分
          if (dayjs(create_time).format('YYYY') === dayjs().format('YYYY')) {
            if (dayjs(create_time).format('MM-DD') !== dayjs().format('MM-DD')) {
              message = dayjs(create_time).format('MM-DD HH:mm')
            } else {
              message = dayjs(create_time).format('HH:mm')
            }
          } else {
            message = dayjs(create_time).format('YYYY-MM-DD HH:mm')
          }
        }
        if (message) {
          list.push({
            mode: 'line',
            message
          })
        }
        lastTime = create_time
        list.push(item)
      })
      return list
    }
  },
  methods: {
    // 切换思考过程的显示/隐藏
    toggleReasoning(item) {
      this.$set(item, 'showReasoning', !item.showReasoning);
    },
    // 设置滚动条
    setScroll(){
      this.$nextTick(() => {
        const contentBox = this.$refs.messageContainer
        contentBox.scrollTop = contentBox.scrollHeight
      })
    },
    handleEnterKey(e) {
      // 检查是否是组合输入（如输入法）的一部分
      if (e.isComposing || e.keyCode === 229) {
        return;
      }
      // 如果按下了shift键，允许换行
      if (e.shiftKey) {
        return;
      }
      e.preventDefault();
      this.sendMessage();
    },
    handleFocus() {
      this.isFocus = true;
      this.setScroll();
    },
    handleBlur() {
      this.isFocus = false;
    },
    async sendMessage() {
      if (this.isLoading) {
        this.$message.warning('正在思考中');
        return
      }
      if (this.isGenerating) {
        this.$message.warning('正在回答中');
        return
      }
      if (!this.message.trim()) {
        this.$message.warning('请输入内容');
        return;
      }

      // 添加用户消息
      this.messageList.push({
        id: undefined,
        mode: 'chat',
        role: 'user',
        content: this.message,
      });

      this.setScroll();
      try {
        await this.createConversation()
        this.isLoading = true
        let sendMsg = this.message
        this.message = '';
        const newMessage = await http.message.create(null, {
          role: 'user',
          content: sendMsg,
          conversation_id: this.conversationId,
        })
        this.messageList[this.messageList.length - 1].id = newMessage.data.id
        // 创建新的助手消息
        const assistantMessage = {
          id: undefined,
          mode: 'chat',
          role: 'assistant',
          reasoning: '',
          answer: '',
          showReasoning: true  // 默认展开思考过程
        };
        this.messageList.push(assistantMessage);

        // 创建 EventSource 连接
        const response = await fetch('/lingxi/deepseek/chat', {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
          },
          body: JSON.stringify({
            model: this.currentModel,
            conversation_id: this.conversationId
          })
        });
        const reader = response.body.getReader();
        const decoder = new TextDecoder();

        while (true) {
          const { done, value } = await reader.read();
          if (done) break;

          // 解码数据
          const chunk = decoder.decode(value);
          const lines = chunk.split('\n');

          // 处理每一行数据
          for (const line of lines) {
            this.isGenerating = true
            if (line.startsWith('data: ')) {
              try {
                const data = JSON.parse(line.slice(6));
                if (data.type === 'reasoning') {
                  assistantMessage.reasoning += data.content;
                } else if (data.type === 'answer') {
                  assistantMessage.answer += data.content;
                }
                console.log('assistantMessage.answer',data)
                this.setScroll();
              } catch (e) {
                console.error('Parse error:', e);
              }
            }
          }
        }
        this.isGenerating = false
        const newAnswer = await http.message.create(null, {
          role: 'assistant',
          reasoning: assistantMessage.reasoning,
          answer: assistantMessage.answer,
          conversation_id: this.conversationId
        })
        this.messageList[this.messageList.length - 1].id = newAnswer.data.id
        // 重置分页状态
        this.page = 1
        this.noMore = false
        this.total = 0
      } catch (error) {
        console.error('Chat error:', error);
        this.$message.error(error.response?.data?.error || '网络错误');
      } finally {
        this.isLoading = false
        this.message = '';
      }
    },
    async createConversation() {
      // 判断当前会话是否存在
      if (!this.conversationId) {
        // 先创建会话
        const res = await http.conversation.create(null, {
          user_id: this.$store.state.user.userInfo.id,
          title: '新会话',
          model: this.currentModel,
          is_archived: 0
        })
        this.conversationId = res.data.id
        // 会话创建成功，替换路由中的会话ID
        await this.$router.replace({
          path: this.$route.path,
          query: {
            conversationId: this.conversationId,
            model: this.currentModel
          }
        });
      }
    },
    // 加载消息列表
    async loadMessages() {
      if (this.isLoadingMore) return
      if (this.noMore) return
      this.isLoadingMore = true
      this.page++;
      try {
        const res = await http.message.page({
          conversation_id: this.conversationId,
          last_message_id: this.messageList[0]?.id,
          pageSize: this.pageSize
        })
        console.log(res)
        let { rows, count } = res.data
        rows = rows.map(item => {
          return {
            mode: 'chat',
            ...item,
            showReasoning: false
          }
        })
        // 因为是倒序查询，所以新消息要添加到前面
        this.messageList = [...rows.reverse(), ...this.messageList]
        this.total = count
        this.noMore = this.messageList.length >= count
        console.log(this.messageList)
      } catch (error) {
        console.error('加载消息失败:', error)
        this.$message.error('加载消息失败')
      } finally {
        this.isLoadingMore = false
      }
    },

    // 处理滚动事件
    handleScroll() {
      const container = this.$refs.messageContainer;
      if (!container) return;
      console.log(container.scrollTop)
      // 当滚动到顶部时加载更多消息
      if (container.scrollTop <= 50) {
        this.loadMessages();
      }
    },
  }
}
</script>
<style lang="scss">
.reasoning-box {
  margin-bottom: 12px;
  border: 1px solid #e6e6e6;
  border-radius: 6px;
  overflow: hidden;

  .reasoning-header {
    padding: 8px 12px;
    background-color: #f5f7fa;
    cursor: pointer;
    display: flex;
    align-items: center;
    font-size: 14px;
    color: #606266;

    i {
      margin-right: 6px;

      &.el-icon-arrow-right {
        margin-left: auto;
        margin-right: 0;
        transition: transform 0.3s;

        &.expanded {
          transform: rotate(90deg);
        }
      }
    }

    &:hover {
      background-color: #e9ecf1;
    }
  }

  .reasoning-content {
    padding: 12px;
    background-color: #fafafa;
    border-top: 1px solid #e6e6e6;
    font-size: 14px;
    line-height: 1.6;
    color: #666;
  }
  .markdown-body {
    font-size: 14px;
  }
}

.chat-content-wrapper {
  border-radius: 8px;
  height: 100%;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  .content-box {
    width: 100%;
    overflow: auto;
    text-align: center;

    h1 {
      font-size: 32px;
      font-weight: 600;
      color: #1C1C28;
      margin-bottom: 12px;
    }

    .subtitle {
      font-size: 16px;
      color: #666;
    }
  }
  .question-title.message-line {
    margin-bottom: 0 !important;
    margin-top: 20px !important;
  }
  .el-textarea__inner {
    border: none;
    resize: none;
    max-height: 150px;
    padding: 0;
    padding-right: 115px;
    color: #000000;
  }
  .el-input__inner {
    color: #000000;
  }
  .right-box {
    position: absolute;
    right: 22px;
    z-index: 2;
    display: flex;
    align-items: center;
    bottom: 0px;
    height: 48px;
    .clear-icon {
      margin-left: 12px;
    }
    img {
      width: 15px;
      height: 15px;
      cursor: pointer;
    }
    .static {
      color: rgb(102, 112, 133);
      background-color: rgb(242, 244, 247);
      padding: 0 4px;
      height: 20px;
      line-height: 20px;
      font-size: 12px;
      border-radius: 6px;
    }
  }
  .el-drawer__header {
    display: none;
  }
  .el-drawer__body {
    padding: 0;
  }
  .chat-list {
    flex-grow: 1;
    overflow: auto;
    .chat-item {
      cursor: pointer;
      margin: 2px 16px;
      display: flex;
      padding: 7px 14px;
      opacity: 0.53;
      font-size: 14px;
      color: #000000;
      letter-spacing: 0;
      line-height: 21px;
      font-weight: 400;
      border-radius: 8px;
      .el-icon {
        margin-top: 3px;
      }
      .inactive {
        display: initial;
      }
      .active {
        display: none;
      }
      &:hover,
      &.active {
        background: #F2F4F7;
        opacity: 1;
        color: #4F4EF1;
        .active {
          display: initial;
        }
        .inactive {
          display: none;
        }
      }
      .chat-item-left {
        overflow: hidden;
        img {
          width: 14px;
          height: 14px;
          margin-top: 3px;
        }

        //overflow: hidden;
        span {
          // 溢出省略号
          overflow: hidden;
          text-overflow: ellipsis;
          white-space: nowrap;
        }
      }
    }
    .more-btn {
      background-color: rgb(239 244 255);
      width: 24px;
      height: 24px;
      border-radius: 6px;
    }
  }
  .footer {
    width: 100%;
    max-width: 800px;
    flex-shrink: 0;
    padding: 24px 0 80px 0;
    .d-line {
      height: 18px;
      width: 1px;
      background-color: #000000;
      opacity: 0.3;
      margin: 0 12px;
    }
    .send-icon {
      flex-shrink: 0;
      width: 22px;
      height: 22px;
      border-radius: 50%;
      display: flex;
      align-items: center;
      justify-content: center;
      cursor: pointer;
      img {
        width: 100%;
        height: 100%;
      }
    }
    .input-box {
      background: #FFFFFF;
      border: 0.5px solid rgba(178,178,178,1);
      box-shadow: 0px 4px 14px 0px rgba(0,0,0,0.04);
      border-radius: 8px;
      min-height: 100px;
      display: flex;
      align-items: center;
      position: relative;
      padding: 5px 5px 5px 10px;
      &.focus {
        border-color: var(--primary-color);
      }
      input::placeholder {
        opacity: 0.5;
        font-family: Arial;
        font-size: 16px;
        color: #000000;
        letter-spacing: 0;
        line-height: 22px;
        font-weight: 400;
      }
      .el-input__inner {
        font-family: Arial;
        font-size: 16px;
        color: #000000;
        letter-spacing: 0;
        line-height: 22px;
        font-weight: 400;
      }
      .el-input__clear {
        width: 16px;
        height: 16px;
      }
      .el-input__wrapper {
        box-shadow: none;
        border-radius: 8px;
      }
    }
  }
  .content {
    width: 100%;
    max-width: 800px;
    overflow-y: auto;
    height: calc(100vh - 200px); // 减去头部和底部的高度
    padding: 0 20px;

    .loading-more {
      text-align: center;
      padding: 10px 0;
      color: #909399;
      font-size: 14px;
      i {
        margin-right: 5px;
      }
    }
    .message-item {
      margin: 8px 0;
      margin-bottom: 16px;
      .reasoning-content {
        padding: 10px;
        background: #f5f7fa;
        border-radius: 4px;
        font-size: 14px;
        color: #666;
      }
    }

    .swiper-list {
      margin: 20px;
      overflow: auto;
      display: flex;
      align-items: center;
      .swiper-item {
        border-radius: 4px;
        margin-right: 12px;
      }
    }
    .question-title {
      display: flex;
      align-items: center;
      margin: 20px 0;
      padding: 0 20px;
      margin-bottom: 8px;

      .question-line {
        flex-grow: 1;
        height: 1px;
      }
      .question-line-start {
        background: linear-gradient(270deg, rgb(243, 244, 246) 0%, rgba(243, 244, 246, 0) 100%);
      }
      .question-line-end {
        background: linear-gradient(270deg, rgba(243, 244, 246, 0) 0%, rgb(243, 244, 246) 100%);
      }
      .date-line {
        background: linear-gradient(270deg, rgb(235, 235, 239) 0%, rgba(243, 244, 246, 0) 100%);
      }
      .question {
        flex-shrink: 0;
        font-family: Arial;
        font-size: 14px;
        color: #667085;
        letter-spacing: 0;
        font-weight: 400;
        padding: 0 12px;
      }
    }
    .question-list {
      display: flex;
      flex-wrap: wrap;
      width: 800px;
      .question-item {
        border-radius: 6px;
        padding: 8px 12px;
        color: #000000;
        letter-spacing: 0;
        font-weight: 400;
        cursor: pointer;
        margin: 12px 6px 0 0;
        background: #f2f4f7;
        border: 0.5px solid #bfbfbf;
        font-family: ArialMT;
        font-size: 12px;
        color: #000000;
        &:hover,
        &.active {
          background:rgba(79,78,241,0.1);
          border: 0.5px solid rgba(79,78,241,0.1);
        }
      }
    }
    .friend {
      display: flex;
      gap: 8px;
      padding-bottom:0;
    }
    .friend-avatar-box {
      display: flex;
      align-items: center;
      .name {
        font-family: ArialMT;
        font-size: 14px;
        color: #000000;
        margin-left: 4px;
      }
    }
    .my {
      display: flex;
      gap: 8px;
      justify-content: flex-end;
      .message {
        padding-top: 8px !important;
        padding-bottom: 8px !important;
      }
    }
    .avatar {
      flex-shrink: 0;
      width: 40px;
      height: 40px;
      border-radius: 50%;
      overflow: hidden;
      img {
        width: 100%;
        height: 100%;
      }
    }
    .message {
      max-width: 100%;
      min-height: 40px;
      font-size: 16px;
      line-height: 24px;
      margin: 0;
      letter-spacing: .25px;
      padding: 12px 24px;
      border-radius: 8px;
      font-weight: 400;
      font-family: ArialMT;
      color: #000000;
      text-align: justify;
      word-wrap: break-word;
      word-break: break-word;
    }
    .friend-message {
      position: relative;
      background: #ffffff;
      border-top-left-radius: 0;
      min-width: 77px;
      .friend-message-border {
        position: absolute;
        color: #F2F4F7;
        top: 0;
        left: -7px;
      }
    }
    .member-message {
      background-color: #4F4EF1;
      color: #ffffff;
      position: relative;
      border-bottom-right-radius: 0;
      padding-left: 24px;
      padding-right: 24px;
      .member-message-border {
        position: absolute;
        top: 0;
        right: -7px;
        color: #4F4EF1;
      }
    }
  }
}
.loading-more {
  text-align: center;
  padding: 10px 0;
  color: #909399;
  font-size: 14px;
  i {
    margin-right: 5px;
  }
}
</style>
